package br.poli.ecomp.adssableccbuilder.builder;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

import org.sablecc.sablecc.syntax3.node.AGrammar;
import org.sablecc.sablecc.syntax3.node.AIgnored;
import org.sablecc.sablecc.syntax3.node.ALeftParserPriority;
import org.sablecc.sablecc.syntax3.node.ALexer;
import org.sablecc.sablecc.syntax3.node.ALexerContext;
import org.sablecc.sablecc.syntax3.node.ANormalParserProduction;
import org.sablecc.sablecc.syntax3.node.AParser;
import org.sablecc.sablecc.syntax3.node.AParserAlternative;
import org.sablecc.sablecc.syntax3.node.AParserContext;

public class SableCCElements {

	private static AGrammar gramatica = null;

	public static Map<String, String> lexicos = new HashMap<String, String>();
	public static Map<String, String> ignorados = new HashMap<String, String>();
	public static Map<String, Expressao> expressoes = new HashMap<String, Expressao>();

	public static boolean extrairComponentes(AGrammar gramatica) {
		boolean resposta = false;
		if (gramatica == null)
			return resposta;
		SableCCElements.gramatica = gramatica;
		extrairLexicosComponentes();
		extrairExpressoesComponentes();
		return resposta;
	}

	private static void extrairLexicosComponentes() {
		lexicos.clear();
		ALexer lex = (ALexer) gramatica.getLexer();
		Object[] exp = lex.getNamedExpressions().toArray();
		String ele = null;
		String[] eleSplit = null;
		for (int i = 0; i < exp.length; i++) {
			ele = exp[i].toString();
			eleSplit = ele.split("=");
			lexicos.put(eleSplit[0], eleSplit[1]);
		}

		ALexerContext content = (ALexerContext) lex.getLexerContexts().get(0);
		AIgnored ignored = (AIgnored) content.getIgnored();
		ignorados.clear();
		ignorados.put(ignored.getIgnoredKeyword().getText(), ignored.getUnit()
				.toString());
	}

	private static void extrairExpressoesComponentes() {
		AParser parser = (AParser) gramatica.getParser();
		expressoes.clear();
		if(parser !=null){
		LinkedList pContext = parser.getParserContexts();
		LinkedList anppLinkList = null;
		AParserContext context = null;
		ANormalParserProduction anpp = null;
		Expressao exp = null;
		for (int i = 0; i < pContext.size(); i++) {
			context = (AParserContext) pContext.get(i);
			anppLinkList = context.getParserProductions();
			for (int j = 0; j < anppLinkList.size(); j++) {
				anpp = (ANormalParserProduction) anppLinkList.get(j);
				exp = new Expressao(anpp.getName().getText());
				exp.setAlternativas(extrairAlternativas(
						anpp.getParserAlternatives(), exp));
				exp.setPrioridades(extrairPrioridades(anpp
						.getParserPriorities()));
				expressoes.put(anpp.getName().getText(), exp);
			}
		}
		}

	}

	private static Map<String, Alternativa> extrairAlternativas(
			LinkedList apaLinkList, Expressao parent) {
		AParserAlternative apa = null;
		Map<String, Alternativa> alternativas = new HashMap<String, Alternativa>();
		String nome;
		String textoAlternativa;
		for (int k = 0; k < apaLinkList.size(); k++) {
			apa = (AParserAlternative) apaLinkList.get(k);
			if (apa.getAlternativeName() != null) {
				nome = apa.getAlternativeName().getText();
				nome = nome.substring(1, nome.length() - 2);
				textoAlternativa = apa.getElements().toString();
				textoAlternativa = textoAlternativa.replace(",", "");
				textoAlternativa = textoAlternativa.substring(1,
						textoAlternativa.length() - 1);
				alternativas.put(nome, new Alternativa(apa.getAlternativeName()
						.getText(), textoAlternativa, parent));
			}
		}
		return alternativas;
	}

	private static String[] extrairPrioridades(LinkedList prioridades) {
		String[] resultado = new String[0];
		if (prioridades != null && prioridades.size() > 0) {
			resultado = new String[prioridades.size()];
			for (int i = 0; i < prioridades.size(); i++) {
				resultado[i] = prioridades.get(i).toString();
			}
		}
		return resultado;
	}

}
